package AsignacionDeRevisores;
import callForPapers.*;

import sistema.*;


import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public abstract class AsignacionDeRevisores {
	public abstract void asignarRevisores(CallForPaper cfp);
	/** Este evento se dispara cuando llega la segunda fecha.
	 * Agarra a todos los papers del cfp dado, y le asigna revisores. Usando la 
	 * lista de revisores que tiene el cfp y el criterio de asignacion. 
	 * */
	
	public List<Usuario> obtenerListaDeRevisores(CallForPaper cfp){ 
    	List<Usuario> listaDeUsuarios = new ArrayList<Usuario>();
    	listaDeUsuarios.addAll(cfp.getRevisores());
    	return listaDeUsuarios; }
	
	public List<Paper> obtenerListaDePapers(CallForPaper cfp){ 
		List<Paper> listaDePapers = new ArrayList<Paper>();
		listaDePapers.addAll(cfp.getPapers());
		return listaDePapers; }	
	
	public Boolean tieneAlMenos1AreaEnComun(List<AreaDeInteres> areasDeInteresPaper , Set<AreaDeInteres> areasDeInteresRevisor){
		List<AreaDeInteres> areasDeRevisor = new ArrayList<AreaDeInteres>();
		areasDeRevisor.addAll(areasDeInteresRevisor); // Transformo un Set en un ArrayList.
		for (AreaDeInteres areaActualPaper: areasDeInteresPaper){
			for (AreaDeInteres areaActualRevisor: areasDeRevisor){ 	
				if (areaActualPaper == areaActualRevisor){ return true; }
			}
		}
		return false;
	}
	public List<Usuario> quitarRevisoresRepetidos(List<Usuario> revisores, List<Usuario> revisoresFiltrados){
		// este metodo devuelve la lista de revisores del CFP sin los revisores filtrados por algun criterio.
		List<Usuario> revisoresNoRepetidos = revisores; // Hago una copia de los revisores
		/** A la lista A le quito los elementos en B.*/
		revisoresNoRepetidos.removeAll(revisoresFiltrados); 
		
		return revisoresNoRepetidos;
	}
	public List<Usuario> completarListaRevisoresAlAzar(List<Usuario> revisores, List<Usuario> revisoresFiltrados){
		// Completa una lista de revisores en caso de que esta sea menor a 3 revisores.
		List<Usuario> revisoresActuales = revisoresFiltrados; // Lista incompleta de revisores
		// Lista de donde voy a sacar para rellenar los revisoresActuales
		List<Usuario> relleno = this.quitarRevisoresRepetidos(revisores, revisoresActuales); 
		int i = 0;
		while (revisoresActuales.size() < 3){
			revisoresActuales.add(relleno.get(i));
			i++;
		}
		return revisoresActuales;
	}
	public List<Usuario> filtrarRevisoresExpertos(List<Usuario> revisores, Paper paper){
		//List<Area> areasPaper = paper.getAreaDeInteres();
		// Hace una sublista de los revisores que son expertos(la mitad más uno)
		List<Usuario>  revisoresFiltrados = new ArrayList<Usuario>(); 
			
		for (Usuario revisorActual: revisores){
			if (this.esExperto(paper,revisorActual)){
				revisoresFiltrados.add(revisorActual);
			}	 
		}
		return revisoresFiltrados; 
	}
	public Boolean esExperto(Paper paper, Usuario revisor){
		Set<AreaDeInteres>  areasPaper = paper.getAreasDeInteres();
		Set<AreaDeInteres>  areasRevisor = revisor.getAreasDeInteres();
		int contador = 0;
		for (AreaDeInteres areaPaperActual: areasPaper){
			// Para cada area de de cada paper
			for ( AreaDeInteres areaRevisorActual: areasRevisor ){
				// Verifico cada expertise del revisor por coincidencias
				// Si la hay, aumento el contador
				if( areaPaperActual == areaRevisorActual ) { contador++; } 
			} 
		}
		// Devolver si las areas en común con el paper son mayor o igual
		// que la mitad más uno.
		return contador >= ( ( areasPaper.size() / 2 ) + 1 );
	}	
	
	public void asignarPapersARevisores(List<Usuario> revisores, List<Paper> listaDePapers){ 
		/**
		 *  A cada paper le asigna 3 revisores
		 *  y a cada usuario le dice que papers debe revisar.
		 * */
		
		int contador = 0; 
		int maximo = revisores.size() - 1;
		
		// usuario.getPapersARevisar().add(dad);
		// paper.getRevisores().add(hgtregh);
		for (Paper paperActual: listaDePapers){
			for(int i=0 ; i<3; i++){
				revisores.get(contador).getPapersARevisar().add(paperActual);
				paperActual.getRevisores().add(revisores.get(contador));	
			// Es el contador si cont < max -> contador++
			// else contador = max -> contador = 0
				contador = chequearContador(contador, maximo);
			}
		}
	}
	public int chequearContador(int indice, int maximo){  
		if ( indice == maximo ){ return 0; }
		else { return ++indice; }
	}

}
